%{
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>  
#include <string.h> 
struct symtab { //定义符号表
        char *name;
        double value;
}symtab[30];      
struct symtab *symlook(char *s); //查找符号表函数
char idstr[50]; 
int Minus_num=0;
int yylex();
extern int yyparse();
FILE* yyin;
void yyerror(const char* s);
%}


%union {
        double  dval;
        struct symtab *symp;
}


%token ADD SUB MUL DIV
%token LB RB
%token UMINUS
%token EQUAL
%token <dval> NUMBER 
%token <symp> ID  


%right EQUAL
%left ADD SUB
%left MUL DIV
%right UMINUS
%left LB RB


%type <dval> expr

%%
lines	:	  lines expr ';'	{ printf("%f\n", $2); }
		| lines ';'
		|
		;

expr	:         expr ADD expr { $$ = $1 + $3; }
		| expr SUB expr { $$ = $1 - $3; }
		| expr MUL expr { $$ = $1 * $3; }
		| expr DIV expr { $$ = $1 / $3; }
		| LB expr RB { $$ = $2; }
		| UMINUS expr %prec UMINUS { $$ = -$2; }
		| NUMBER { $$ = $1; }
		| ID EQUAL expr { $1->value=$3; $$=$3;}
		| ID {$$=$1->value;}  
		;


%%
int yylex()
{
	int t;
	while (1)
	{
		t = getchar();
		if (t == ' ' || t == '\n' || t == '\t') 
		{ 
		//do nothing
		Minus_num=0;
		 }
		else if (isdigit(t))
		{
			int val=0;
			while (isdigit(t))
			{
				val=val*10+t-'0';
				t = getchar();
			}
			yylval.dval=val;
			ungetc(t, yyin);
			Minus_num=1;
			return NUMBER;
		}
		else if ((t>='a'&&t<='z')||(t>='A'&&t<='Z')||(t=='_'))
		{
			int val=0;
			while ((t>='a'&&t<='z')||(t>='A'&&t<='Z')||(t=='_')||(t>='0'&&t<='9'))
			{
				idstr[val]=t;
				t = getchar();
				val++;
			}
			idstr[val]='\0';
			char* temp = (char*)malloc (50*sizeof(char)); 
			strcpy(temp,idstr);
			yylval.symp=symlook(temp); 
			ungetc(t, yyin);
			Minus_num=1;
			return ID;
		}
		else if (t =='+')
		{
		Minus_num=0;
		       return ADD;
		}
		else if (t == '-')
		{
		if(Minus_num)
			return SUB;
		else
			return UMINUS;
		Minus_num=0;
		} 
		else if (t =='*')
		{
		Minus_num=0;
		       return MUL;
		       
		}
		else if (t =='/')
		{
		Minus_num=0;
		       return DIV;
		}
		else if (t == '(')
		{
		Minus_num=0;
			return LB;
		}
		else if (t ==')')
		{
		Minus_num=0;
		       return RB;
		}
               else if (t == '=')
		{
		Minus_num=0;
			return EQUAL;
		}
		else
		{
		Minus_num=0;
			return t;
		}
	}
}

int main()
{
	yyin = stdin;
	do {
		yyparse();
	} while (!feof(yyin));
	return 0;
}
void yyerror(const char* s) {
	fprintf(stderr, "Parse error: %s\n", s);
	exit(1);
}

struct symtab* symlook(char *s){
    char *p;
    struct symtab *sp;
    for(sp=symtab;sp<&symtab[20];sp++){
        if(sp->name && !strcmp(sp->name,s))
            return sp;
        if(!sp->name){
            sp->name=strdup(s);
            return sp;
            }
        }
        yyerror("Wrong input");
        exit(1);
}
